home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / kmsg / RCS / kmsg.c,v < prev    next >
Encoding:
Text File  |  1992-06-11  |  14.6 KB  |  652 lines

  1. head     1.7;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.7
  10. date     92.06.10.17.19.19;  author jhh;  state Exp;
  11. branches ;
  12. next     1.6;
  13.  
  14. 1.6
  15. date     91.10.22.14.25.01;  author jhh;  state Exp;
  16. branches ;
  17. next     1.5;
  18.  
  19. 1.5
  20. date     91.06.21.18.24.46;  author mottsmth;  state Exp;
  21. branches ;
  22. next     1.4;
  23.  
  24. 1.4
  25. date     91.02.02.15.22.09;  author jhh;  state Exp;
  26. branches ;
  27. next     1.3;
  28.  
  29. 1.3
  30. date     89.06.16.08.49.06;  author brent;  state Exp;
  31. branches ;
  32. next     1.2;
  33.  
  34. 1.2
  35. date     89.06.02.15.21.13;  author mgbaker;  state Exp;
  36. branches ;
  37. next     1.1;
  38.  
  39. 1.1
  40. date     88.10.26.10.28.44;  author ouster;  state Exp;
  41. branches ;
  42. next     ;
  43.  
  44.  
  45. desc
  46. @@
  47.  
  48.  
  49. 1.7
  50. log
  51. @ported to new Host library
  52. @
  53. text
  54. @/* 
  55.  * kmsg.c --
  56.  *
  57.  *    Program that sends debugging messages to a Sprite kernel.
  58.  *    Can be used to put a kernel into the debugger, query it,
  59.  *    and resume from the debugger.
  60.  *
  61.  * Copyright 1988 Regents of the University of California
  62.  * Permission to use, copy, modify, and distribute this
  63.  * software and its documentation for any purpose and without
  64.  * fee is hereby granted, provided that the above copyright
  65.  * notice appear in all copies.  The University of California
  66.  * makes no representations about the suitability of this
  67.  * software for any purpose.  It is provided "as is" without
  68.  * express or implied warranty.
  69.  */
  70.  
  71. #ifndef lint
  72. static char rcsid[] = "$Header: /sprite/src/cmds/kmsg/RCS/kmsg.c,v 1.6 91/10/22 14:25:01 jhh Exp Locker: jhh $ SPRITE (Berkeley)";
  73. #endif not lint
  74.  
  75. #include <errno.h>
  76. #include <host.h>
  77. #include <net.h>
  78. #include <option.h>
  79. #include <stdio.h>
  80. #include <string.h>
  81. #include <sys/file.h>
  82. #include <kernel/dbg.h>
  83.  
  84. #include <signal.h>
  85. #include <sys/types.h>
  86. #include <sys/socket.h>
  87. #include <sys/time.h>
  88. #include <netinet/in.h>
  89. #include <netdb.h>
  90. #include <sgtty.h>
  91.  
  92. /*
  93.  * Library imports:
  94.  */
  95.  
  96. extern void panic();
  97.  
  98. /*
  99.  * Message buffers.
  100.  */
  101. static Dbg_Msg    msg;
  102. static int    msgSize;
  103. #define    REPLY_BUFFER_SIZE    4096
  104. static    char    replyBuffer[REPLY_BUFFER_SIZE];
  105. static    char    requestBuffer[DBG_MAX_REQUEST_SIZE];
  106. /*
  107.  * The decstation currently supports both kdbx and kgdb.   Since we
  108.  * are using the kgdb interface we must start the message number 
  109.  * at 0x40000000 so the debugger stub uses the right interface.
  110.  */
  111. #if defined(ds3100) || defined(ds5000)
  112. static    int    msgNum = 0x40000000;
  113. #else
  114. static    int    msgNum = 0;
  115. #endif
  116.  
  117. extern void    RecvReply();
  118.  
  119. static    struct sockaddr_in    remote;
  120. int                kdbxTimeout = 1;
  121. static    int            netSocket;
  122.  
  123. /*
  124.  *----------------------------------------------------------------------
  125.  *
  126.  * CreateSocket --
  127.  *
  128.  *    Creates a UDP socket connected to the Sprite host's kernel 
  129.  *    debugger port.
  130.  *
  131.  * Results:
  132.  *    The stream ID of the socket.
  133.  *
  134.  * Side effects:
  135.  *    None.
  136.  *
  137.  *----------------------------------------------------------------------
  138.  */
  139. int
  140. CreateSocket(spriteHostName)
  141.     char    *spriteHostName;
  142. {
  143.     int            socketID;
  144.     struct hostent     *hostPtr;
  145.  
  146.     hostPtr = gethostbyname(spriteHostName);
  147.     if (hostPtr == (struct hostent *) NULL) {
  148.     (void) fprintf(stderr, "CreateSocket: unknown host \"%s\"\n",
  149.         spriteHostName);
  150.     exit(1);
  151.     }
  152.     if (hostPtr->h_addrtype != AF_INET) {
  153.     (void) fprintf(stderr, "CreateSocket: bad address type for host %s\n", 
  154.         spriteHostName);
  155.     exit(2);
  156.     }
  157.  
  158.     socketID = socket(AF_INET, SOCK_DGRAM, 0);
  159.     if (socketID < 0) {
  160.     perror("CreateSocket: socket");
  161.     exit(3);
  162.     }
  163.  
  164.     bzero((char *) &remote, sizeof(remote));
  165.     bcopy((char *) hostPtr->h_addr, (char *) &remote.sin_addr,
  166.         hostPtr->h_length);
  167.     remote.sin_port = htons(DBG_UDP_PORT);
  168.     remote.sin_family = AF_INET;
  169.  
  170.     if (connect(socketID, (struct sockaddr *) &remote, sizeof(remote)) < 0) {
  171.     perror("CreateSocket: connect");
  172.     exit(4);
  173.     }
  174.  
  175.     return(socketID);
  176. }
  177.  
  178. /*
  179.  * ----------------------------------------------------------------------------
  180.  *
  181.  *  SendRequest --
  182.  *
  183.  *     Send a request message to the kernel.
  184.  *
  185.  * Results:
  186.  *     None.
  187.  *
  188.  * Side effects:
  189.  *     None.
  190.  * ----------------------------------------------------------------------------
  191.  */
  192. static void
  193. SendRequest(numBytes)
  194.     int    numBytes;
  195. {
  196.     Dbg_Opcode    opcode;
  197.  
  198.     msgSize = numBytes;
  199.     msgNum++;
  200.     *(int *)requestBuffer = msgNum;
  201.     bcopy((char *) &msg, requestBuffer + 4, numBytes);
  202.     if (write(netSocket, requestBuffer, numBytes + 4) < numBytes + 4) {
  203.     panic("SendRequest: Couldn't write to the kernel socket\n");
  204.     return;
  205.     }
  206.     opcode = (Dbg_Opcode) msg.opcode;
  207.     if (opcode == DBG_DETACH) {
  208.     int    dummy;
  209.     /*
  210.      * Wait for explicit acknowledgments of these packets.
  211.      */
  212.     RecvReply(opcode, 4, (char *) &dummy, (int *) NULL, 1);
  213.     }
  214. }
  215.  
  216. /*
  217.  * ----------------------------------------------------------------------------
  218.  *
  219.  *  RecvReply --
  220.  *
  221.  *     Receive a reply from the kernel.
  222.  *
  223.  * Results:
  224.  *     None.
  225.  *
  226.  * Side effects:
  227.  *     None.
  228.  * ----------------------------------------------------------------------------
  229.  */
  230.  
  231.     /* ARGSUSED */
  232. static void
  233. RecvReply(opcode, numBytes, destAddr, readStatusPtr, timeout)
  234.     Dbg_Opcode    opcode;
  235.     int        numBytes;
  236.     char    *destAddr;
  237.     int        *readStatusPtr;
  238.     int        timeout;
  239. {
  240.     int        status;
  241.     int        readMask;
  242.     struct    timeval    interval;
  243.     int        bytesRead;
  244.  
  245.  
  246.     if (numBytes + 8 > REPLY_BUFFER_SIZE) {
  247.     panic("numBytes <%d> > REPLY_BUFFER_SIZE <%d>\n",
  248.             numBytes + 8, REPLY_BUFFER_SIZE);
  249.     }
  250.     interval.tv_sec = kdbxTimeout;
  251.     interval.tv_usec = 0;
  252.     do {
  253.     if (timeout) {
  254.         int    numTimeouts;
  255.  
  256.         numTimeouts = 0;
  257.         /*
  258.          * Loop timing out and sending packets until a new packet
  259.          * has arrived.
  260.          */
  261.         do {
  262.         readMask = 1 << netSocket;
  263.         status = select(32, &readMask, (int *) NULL,
  264.             (int *) NULL, &interval);
  265.         if (status == 1) {
  266.             break;
  267.         } else if (status == -1) {
  268.             panic("RecvReply: Couldn't select on socket.\n");
  269.         } else if (status == 0) {
  270.             SendRequest(msgSize);
  271.             numTimeouts++;
  272.             if (numTimeouts % 10 == 0) {
  273.             (void) fprintf(stderr, "Timing out and resending\n");
  274.             (void) fflush(stderr);
  275.             }
  276.         }
  277.         } while (1);
  278.     }
  279.     if (opcode == DBG_GET_VERSION_STRING) {
  280.         /*
  281.          * Returning the version string returns a variable length packet.
  282.          */
  283.         bytesRead = read(netSocket, replyBuffer, numBytes);
  284.         if (bytesRead < 0) {
  285.         perror("RecvReply: Error reading socket.");
  286.         panic("exiting");
  287.         }
  288.         (void) strcpy(destAddr, (char *)(replyBuffer + 4));
  289.         return;
  290.     } else {
  291.         /*
  292.          * Normal request so just read in the message which includes
  293.          * the message number.
  294.          */
  295.         bytesRead = read(netSocket, replyBuffer, numBytes + 4);
  296.         if (bytesRead < 0) {
  297.         panic("RecvReply: Error reading socket (2).");
  298.         }
  299.         /*
  300.          * Check message number before size because it could be
  301.          * an old packet.
  302.          */
  303.         if (*(int *)replyBuffer != msgNum) {
  304.         continue;
  305.         }
  306.         if (bytesRead != numBytes + 4) {
  307.         (void) printf("RecvReply: Short read (2): op=%d exp=%d read=%d",
  308.             opcode, numBytes + 4, bytesRead);
  309.         }
  310.         if (*(int *)replyBuffer != msgNum) {
  311.         continue;
  312.         }
  313.         bcopy(replyBuffer + 4, destAddr, numBytes);
  314.         return;
  315.     }
  316.     } while (1);
  317. }
  318.  
  319. /*
  320.  * ----------------------------------------------------------------------------
  321.  *
  322.  * SendCommand --
  323.  *
  324.  *     Write the command over to the kernel.  
  325.  *
  326.  * Results:
  327.  *     None.
  328.  *
  329.  * Side effects:
  330.  *     None.
  331.  *
  332.  * ----------------------------------------------------------------------------
  333.  */
  334. void
  335. SendCommand(opcode, srcAddr, destAddr, numBytes)
  336.     Dbg_Opcode    opcode;        /* Which command */
  337.     char    *srcAddr;    /* Where to read data from */
  338.     char    *destAddr;    /* Where to write data to */
  339.     int        numBytes;    /* The number of bytes to read or write */
  340. {
  341.     msg.opcode = (short) opcode;
  342.  
  343.     switch (opcode) {
  344.     case DBG_GET_STOP_INFO:
  345.         SendRequest(sizeof(msg.opcode));
  346.         RecvReply(opcode, numBytes, destAddr, (int *) NULL, 1);
  347.         break;
  348.     case DBG_DETACH:
  349.         msg.data.pc = *(int *) srcAddr;
  350.         SendRequest(sizeof(msg.opcode) + sizeof(msg.data.pc));
  351.         break;
  352.     case DBG_GET_VERSION_STRING:
  353.         SendRequest(sizeof(msg.opcode));
  354.         RecvReply(opcode, numBytes, destAddr, (int *) NULL, 1);
  355.         break;
  356.     case DBG_REBOOT:
  357.         if (numBytes > 0) {
  358.         (void) strcpy(msg.data.reboot.string, (char *)srcAddr);
  359.         }
  360.         msg.data.reboot.stringLength = numBytes;
  361.         SendRequest(sizeof(msg.opcode) +
  362.             sizeof(msg.data.reboot.stringLength) +
  363.             msg.data.reboot.stringLength);
  364.         break;
  365.     default:
  366.         (void) printf("Unknown opcode %d\n", opcode);
  367.     }
  368. }
  369.  
  370. /*
  371.  *----------------------------------------------------------------------
  372.  *
  373.  * SendDebug --
  374.  *
  375.  *    Given a host name, this procedure sends a command to that host
  376.  *    that causes it to enter the debugger.
  377.  *
  378.  * Results:
  379.  *    0 if everything went well, 1 if there was some sort of error
  380.  *    (in this case an error message is printed).
  381.  *
  382.  * Side effects:
  383.  *    The given host will enter the debugger, if the host exists and
  384.  *    is running Sprite.
  385.  *
  386.  *----------------------------------------------------------------------
  387.  */
  388.  
  389. int
  390. SendDebug(hostName)
  391.     char *hostName;        /* Name of Sprite host. */
  392. {
  393.     Host_Entry *host;
  394.     int streamID, amtWritten;
  395.  
  396.     /*
  397.      * A debug packet contains the name of the host that is issuing
  398.      * the "enter debugger" command.  Changed 'int nameLen' to be
  399.      * 'char nameLenChar[]' in the packet struct to remove padding
  400.      * bytes which were confusing the kernel. JMS
  401.      */
  402.  
  403. #define MAX_NAME_LEN    100
  404.     struct {
  405.     Net_EtherHdr    etherHdr;
  406.     char         nameLenChar[sizeof(int)];
  407.     char        name[MAX_NAME_LEN];
  408.     } packet;
  409.  
  410.     int nameLen;
  411.     int i;
  412.  
  413.     /*
  414.      * Fill in our name in the debug packet.
  415.      */
  416.  
  417.     if (gethostname(packet.name, MAX_NAME_LEN-1) != 0) {
  418.     (void) fprintf(stderr, "Couldn't find my host name: %s\n",
  419.         strerror(errno));
  420.     return 1;
  421.     }
  422.     packet.name[MAX_NAME_LEN-1] = 0;
  423.     nameLen = strlen(packet.name);
  424.     bcopy((char *) &nameLen, packet.nameLenChar, sizeof(int));
  425.     if (strcmp(packet.name, hostName) == 0) {
  426.     (void) fprintf(stderr, "Can't send a debug packet to yourself.\n");
  427.     return 1;
  428.     }
  429.  
  430.     /*
  431.      * Set up the ethernet packet header. The source address is filled
  432.      * in by the kernel.
  433.      */
  434.     host = Host_ByName(hostName);
  435.     if (host == (Host_Entry *)NULL) {
  436.     (void) fprintf(stderr, "Unknown host: %s\n", hostName);
  437.     return 1;
  438.     }
  439.     for (i = 0; i < host->numNets; i++) {
  440.     if (host->nets[i].netAddr.type == NET_ADDRESS_ETHER) {
  441.         bcopy((char *) &host->nets[i].netAddr.address.ether,
  442.         (char *) &packet.etherHdr.destination, 
  443.         sizeof(Net_EtherAddress));
  444.         break;
  445.     }
  446.     }
  447.     packet.etherHdr.type = htons(NET_ETHER_SPRITE_DEBUG);
  448.  
  449.     streamID = open("/dev/etherSpriteDebug", O_WRONLY, 0666);
  450.     if (streamID < 0) {
  451.     (void) fprintf(stderr, "Couldn't open raw ethernet device: %s\n",
  452.         strerror(errno));
  453.     return 1;
  454.     }
  455.  
  456.     amtWritten = write(streamID, (char *) &packet, sizeof(packet));
  457.     if (amtWritten < 0) {
  458.     (void) fprintf(stderr, "Error sending debug packet: %s\n",
  459.         strerror(errno));
  460.     return 1;
  461.     }
  462.     if (amtWritten != sizeof(packet)) {
  463.     (void) fprintf(stderr, "Short write for packet: %d\n", amtWritten);
  464.     return 1;
  465.     }
  466.     return 0;
  467. }
  468.  
  469. /*
  470.  *----------------------------------------------------------------------
  471.  *
  472.  * main --
  473.  *
  474.  *    Main program for "kmsg".
  475.  *
  476.  * Results:
  477.  *    None.
  478.  *
  479.  * Side effects:
  480.  *    Causes things to happen in a target machine.  See the man page
  481.  *    for details.
  482.  *
  483.  *----------------------------------------------------------------------
  484.  */
  485.  
  486. int    getVersion = 0;
  487. int    debug = 0;
  488. int    detach = 0;
  489. char    *versionString = (char *)NULL;
  490. int    reboot = 0;
  491. char    *rebootString = (char *)NULL;
  492.  
  493. Option optionArray[] = {
  494.     {OPT_TRUE, "c", (char *) &detach,
  495.     "Continue the kernel"},
  496.     {OPT_TRUE, "d", (char *) &debug,
  497.     "Force kernel into the debugger"},
  498.     {OPT_TRUE, "r", (char *) &reboot,
  499.     "Reboot the machine using the empty string"},
  500.     {OPT_STRING, "R", (char *) &rebootString,
  501.     "Reboot the machine using the given string"},
  502.     {OPT_STRING, "s", (char *) &versionString,
  503.     "Version string to compare version of kernel to (implies -v)"},
  504.     {OPT_TRUE, "v", (char *) &getVersion,
  505.     "Print out the version of the kernel."},
  506. };
  507.  
  508. main(argc, argv)
  509.     int        argc;
  510.     char    **argv;
  511. {
  512.     StopInfo    stopInfo;
  513.     char    buffer[100];
  514.  
  515.     argc = Opt_Parse(argc, argv, optionArray, Opt_Number(optionArray), 0);
  516.     if (argc != 2) {
  517.     (void) fprintf(stderr, "Usage:  %s [options] hostname\n", argv[0]);
  518.     exit(1);
  519.     }
  520.     if (debug) {
  521.     if (SendDebug(argv[1]) != 0) {
  522.         exit(1);
  523.     }
  524.     }
  525.     netSocket = CreateSocket(argv[1]);
  526.     if (detach) {
  527.     SendCommand(DBG_GET_STOP_INFO, (char *)NULL, (char *)&stopInfo,
  528.             sizeof(stopInfo));
  529. #ifdef sun3
  530.     SendCommand(DBG_DETACH, (char *) &stopInfo.pc, (char *)NULL,
  531.             sizeof(stopInfo.pc));
  532. #else
  533.     SendCommand(DBG_DETACH, (char *) &stopInfo.regs.pc, (char *)NULL,
  534.             sizeof(stopInfo.regs.pc));
  535. #endif /* sun3 */
  536.     }
  537.     if (getVersion || versionString != (char *)NULL) {
  538.     SendCommand(DBG_GET_VERSION_STRING, (char *)0, buffer, 100);
  539.     (void) printf("%s\n", buffer);
  540.     if (versionString != (char *)NULL) {
  541.         exit(strcmp(buffer, versionString));
  542.     }
  543.     }
  544.     if (rebootString != (char *)NULL) {
  545.     SendCommand(DBG_REBOOT, rebootString, (char *)NULL,
  546.             strlen(rebootString));
  547.     } else if (reboot) {
  548.     SendCommand(DBG_REBOOT, (char *)NULL, (char *)NULL, 0);
  549.     }
  550.  
  551.     exit(0);
  552. }
  553. @
  554.  
  555.  
  556. 1.6
  557. log
  558. @added decstation support
  559. @
  560. text
  561. @d19 1
  562. a19 1
  563. static char rcsid[] = "$Header: /sprite/src/cmds/kmsg/sun3.md/RCS/kmsg.c,v 1.5 91/06/21 18:24:46 mottsmth Exp $ SPRITE (Berkeley)";
  564. d358 1
  565. d386 8
  566. a393 2
  567.     bcopy((char *) host->netAddr.etherAddr,
  568.         (char *) &packet.etherHdr.destination, HOST_ETHER_ADDRESS_SIZE);
  569. @
  570.  
  571.  
  572. 1.5
  573. log
  574. @removed padding bytes from packet struct
  575. by changing packet.nameLen from int to char[sizeof(int)].
  576. @
  577. text
  578. @d19 1
  579. a19 1
  580. static char rcsid[] = "$Header: /sprite/src/cmds/kmsg/sun3.md/RCS/kmsg.c,v 1.4 91/02/02 15:22:09 jhh Exp $ SPRITE (Berkeley)";
  581. d53 8
  582. d62 1
  583. d469 4
  584. a472 1
  585. #ifdef sun4
  586. d475 1
  587. a475 4
  588. #else
  589.     SendCommand(DBG_DETACH, (char *) &stopInfo.pc, (char *)NULL,
  590.             sizeof(stopInfo.pc));
  591. #endif /* sun4 */
  592. @
  593.  
  594.  
  595. 1.4
  596. log
  597. @packet type must be in network byte order.
  598. @
  599. text
  600. @d19 1
  601. a19 1
  602. static char rcsid[] = "$Header: /sprite/src/cmds/kmsg/RCS/kmsg.c,v 1.3 89/06/16 08:49:06 brent Exp Locker: jhh $ SPRITE (Berkeley)";
  603. d336 3
  604. a338 1
  605.      * the "enter debugger" command.
  606. d344 1
  607. a344 1
  608.     int         nameLen;
  609. d348 2
  610. d360 2
  611. a361 1
  612.     packet.nameLen = strlen(packet.name);
  613. @
  614.  
  615.  
  616. 1.3
  617. log
  618. @Tweaked error message.
  619. @
  620. text
  621. @d19 1
  622. a19 1
  623. static char rcsid[] = "$Header: /a/newcmds/kmsg/RCS/kmsg.c,v 1.1 88/10/26 10:28:44 ouster Exp Locker: mgbaker $ SPRITE (Berkeley)";
  624. d373 1
  625. a373 1
  626.     packet.etherHdr.type = NET_ETHER_SPRITE_DEBUG;
  627. @
  628.  
  629.  
  630. 1.2
  631. log
  632. @Added hook for sun4 DBG_DETACH
  633. @
  634. text
  635. @d223 2
  636. a224 1
  637.         panic("RecvReply: Error reading socket.");
  638. @
  639.  
  640.  
  641. 1.1
  642. log
  643. @Initial revision
  644. @
  645. text
  646. @d19 1
  647. a19 1
  648. static char rcsid[] = "$Header: proto.c,v 1.2 88/03/11 08:39:08 ouster Exp $ SPRITE (Berkeley)";
  649. d454 4
  650. d460 1
  651. @
  652.